Conversation
| const [contentData, setContentData] = useState(null); | ||
|
|
||
| useEffect(() => { | ||
| const apiUrl = "/api/contents/:contents_id"; // 서버 API 엔드포인트 URL |
There was a problem hiding this comment.
여기 문제가 있는 부분: api 문서에서 "/:contents_id"라고 적은 부분은 /1, /2처럼 "/" 뒤에 contents_id에 해당하는 숫자를 붙일 수 있어서 그런 건데, 이 부분 설명이 부족했던 것 같네ㅠㅜ
지금처럼 url을 만들면 /api/contents/:contents_id로 요청이 가니까, /api/contents/1이나 /api/contents/2처럼 현재 페이지의 contentId가 들어가는 문자열을 apiURL로 사용하게 바꿔야 할 듯
There was a problem hiding this comment.
오케이 확인~~ 그런 방식으로도 짰다가 오류 떠서 아닌가 싶었는데 맞았네용
| var id = props.id; | ||
| let content = contentsData[id]; | ||
| var id = props.contentId; | ||
| // const contentToPlay = contentsData[id]; | ||
|
|
||
| const [contentData, setContentData] = useState(null); | ||
|
|
||
| useEffect(() => { | ||
| const apiUrl = "/api/contents/:contents_id"; // 서버 API 엔드포인트 URL | ||
|
|
||
| fetch(apiUrl) | ||
| .then((response) => response.json()) | ||
| .then((Content) => { | ||
| setContentData(Content); | ||
| }) | ||
| .catch((error) => { | ||
| console.error("Error fetching data:", error); | ||
| }); | ||
| }, []); | ||
|
|
||
| console.log(contentData); | ||
| var contentToPlay = contentData; |
There was a problem hiding this comment.
여기가 요주의 부분인데, 코드를 보자면
- contentData라는 state가 선언되어 있다
- useEffect 부분에서 apiUrl으로 요청을 날린다
- 성공하면 contentData state에 응답을 저장하고, 실패하면 에러를 날린다
- contentToPlay 변수에 contentData를 지정한다
요렇게 돌아가고, 이 밑에 부분을 보면 컴포넌트를 다음과 같이 렌더하고 있지
A. contentToPlay.type이 유튜브가 아니면 "잘못된 접근"이라고 표시
B. 그렇지 않으면 제대로 된 컴포넌트를 리턴
두 단계로 나눠서 문제를 생각해보자.
단계 1) 먼저 4는 왜 필요할까? useEffect가 작동하고 난 다음에, 즉 contentData에 값이 생긴 이후에 그 값을 contentToPlay에 저장하고 사용하고 싶은 거??
-> 리액트의 작동 원리는 먼저 컴포넌트 내부의 모든 코드를 작동시킨 다음 컴포넌트를 생성(return)하고, 혹시 상태에 변경이 생긴다면 다시 모든 코드를 작동시켜서 새로운 상태의 컴포넌트를 return 하는 식이야. 그리고, useEffect는 첫 번째 생성이 일어난 후에 한 번 작동하는 훅. 즉, contentToPlay를 useEffect 다음에 적어놨다고 해도, 컴포넌트 내부의 코드임으로 먼저 작동한 다음에 useEffect가 실행된다. 따라서 아무 값도 없을 때(fetch가 끝나기 전) contentToPlay를 선언하고, 이 contentToPlay.type을 확인해서 조건문을 거니까 에러가 나는 것!
단계 2) 그럼 값이 있을 때만 컴포넌트를 리턴하려면 어떻게 해야할까?
-> 먼저 contentToPlay를 다시 선언하는 건 별 의미가 없으니까 잊어버리고, contentData라는 상태만 봐보자. contentData는 일단 아무 값도 없다가, useEffect를 작동하고 나면 값이 있어지거나, 여전히 없을 거야. 즉 contentData의 분기는 값이 없을 때 , 값이 있지만 type이 youtube가 아닐 때, 값이 있고 type도 youtube일 때의 세 가지로 나뉠거야! 그리고 이는 각각 로딩 중, 잘못된 로드, 제대로 된 로드에 해당하는 상황이니까, 아래처럼 if문을 이용한 조건부 렌더링으로 세 상태의 컴포넌트를 불러 오는 게 제일 편한 방법일거야.
추가 팁) contentData에 값이 없을 때에는 contentData===undefined나, !contentData로 간단히 체크 가능
There was a problem hiding this comment.
와우 너무 필요한 설명이다 잘 이해됐음 ㅎㅎ 반영해서 해볼게!
그리고
fetch(apiUrl) .then((response) => response.json()) .then((Content) => { setContentData(Content); })
이 부분에서 setContentData()안에 들어가는 게 Content가 맞을까? 이 부분 문법을 잘 몰라서 Content로 값을 전달받으니까 일단 이렇게 넣었는데
There was a problem hiding this comment.
아 저기는 너가 편한대로 이름 붙이면 괜찮! 두번째 .then() 안에 들어가는 화살표 함수가 (앞에서 보낸 데이터)=>{ setContentData(앞에서 보낸 데이터)} 같은 꼴이잖아? 이 때 앞에서 보낸 데이터는 너가 이름 붙이기 나름이여! 뭐 data로 해도 되고, response로 해도 되고, content로 해도 되고... 그냥 이해가 잘 되는 이름이면 괜찮
단 대문자로 시작하는 이름은 '컴포넌트'나 '타입'에 붙이는데, 이건 그냥 '값'이니까 Content보단 content가 나을듯! 그리고 관습적으로는 response.json()으로 변환한 응답이니까 parsedResponse같은 이름을 붙이는 경우도 많은 듯
요약
관련 이슈
#22
체크리스트
PR 달 때
yarn build로 테스트를 했나요?머지하기 전에
작업 내용
논의가 필요한 사항